package gui;

import com.google.inject.Inject;
import gui.timecontrols.FixedTimeControl;
import gui.timecontrols.MovesPerSession;
import gui.timecontrols.TimeControls;
import gui.timecontrols.UseTimeIncrement;
import org.eclipse.jface.viewers.IStructuredSelection;
import tournamentmanager.*;

import java.io.IOException;

public class Controller {  
  private final TourneyManView tourneyManView;
  private final Preferences model;
  private TimeControls timeControls;
  public static final int MAX_GAMES = 99999;
  public static final String TIME_INC = "Use time increment";
  public static final String FIXED = "Use fixed time control";
  public static final String MOVES_PER_SESSION = "Use moves per session";
  public static final String[] timeControlTypes = {TIME_INC, FIXED, MOVES_PER_SESSION};

  @Inject
  public Controller(TourneyManView tourneyManView, Preferences model) {
    this.tourneyManView = tourneyManView;
    this.model = model;
  }

  public void loadViewFromModel() {
    loadSelectedTabFromModel();
    loadOutPgnFileFromModel();
    loadRoundRobinTabFromModel();
    loadSimulTabFromModel();
    Tournament trn = model.getCurrentTournament();
    int timeIncrement = trn.getTimeIncrement();
    if (timeIncrement == -1) {
      timeControls = new MovesPerSession(tourneyManView, model);
    }
    if (timeIncrement == 0) {
      timeControls = new FixedTimeControl(tourneyManView, model);
    }
    if (timeIncrement > 0) {
      timeControls = new UseTimeIncrement(tourneyManView, model);
    }
    timeControls.loadFromModel();
    loadProgressBarFromModel();
    refreshViewers();
  }

  public void saveModelFromView() throws IOException {
    updateModelFromView();
    model.save();
  }

  public void updateModelFromView() {
    Tournament trn = tourneyManView.tabFolder.getSelectionIndex() == 1 ? model.getSimulTournament() : model.getRoundRobinTournament();
    model.setCurrentTournament(trn);
    IStructuredSelection selection = (IStructuredSelection)tourneyManView.simulViewer.getSelection();
    ChessEngine engine = (ChessEngine)selection.getFirstElement();
    model.getSimulTournament().setSimulEngine(engine);
    model.getSimulTournament().setCycles(tourneyManView.spnSimulCycles.getSelection());
    model.getRoundRobinTournament().setMatchRounds(tourneyManView.spnMatchRounds.getSelection());
    trn.setOutPGNFile(tourneyManView.txtOutPGNFile.getText());
    trn.setTimeControl(tourneyManView.spnTimeControl.getSelection());
    String type = timeControlTypes[tourneyManView.chcTimeControlType.getSelectionIndex()];
    if (type.equals(TIME_INC)) {
      timeControls = new UseTimeIncrement(tourneyManView, model);
    }
    if (type.equals(FIXED)) {
      timeControls = new FixedTimeControl(tourneyManView, model);
    }
    if (type.equals(MOVES_PER_SESSION)) {
      timeControls = new MovesPerSession(tourneyManView, model);
    }
    timeControls.loadFromView();
  }

  private void loadOutPgnFileFromModel() {
    tourneyManView.txtOutPGNFile.setText(model.getCurrentTournament().getOutPGNFile());
  }

  private void refreshViewers() {
    tourneyManView.preConfEnginesViewer.refresh();
    tourneyManView.trnEnginesViewer.refresh();
    tourneyManView.simulViewer.refresh();
  }

  private void loadProgressBarFromModel() {
    tourneyManView.pbTrn.setMinimum(0);
    tourneyManView.pbTrn.setSelection(model.getCurrentTournament().getGamesPlayed());
    if (model.getCurrentTournament().getGamesToPlay() == 0) {
      tourneyManView.pbTrn.setMaximum(MAX_GAMES);
    }
    else {
      tourneyManView.pbTrn.setMaximum(model.getCurrentTournament().getGamesToPlay());
    }
    tourneyManView.pbTrn.redraw();
  }

  private void loadSelectedTabFromModel() {
    Tournament trn = model.getCurrentTournament();
    if (trn instanceof RoundRobinTournament) {
      tourneyManView.tabFolder.setSelection(0);
    }
    if (trn instanceof SimulTournament) {
      tourneyManView.tabFolder.setSelection(1);
    }
  }

  private void loadSimulTabFromModel() {
    SimulTournament simulTrn = model.getSimulTournament();
    ChessEngine engine = simulTrn.getSimulEngine();
    for (int i = 0; i <= tourneyManView.lstPreconfEngines.getItemCount(); i++) {
      ChessEngine e = (ChessEngine)tourneyManView.preConfEnginesViewer.getElementAt(i);
      if (engine == e) {
        tourneyManView.chcMainSimulEnginge.select(i);
      }
    }
    tourneyManView.spnSimulCycles.setSelection(simulTrn.getCycles());
  }

  private void loadRoundRobinTabFromModel() {
    RoundRobinTournament robinTrn = model.getRoundRobinTournament();
    tourneyManView.spnMatchRounds.setSelection(robinTrn.getMatchRounds() / 2);
  }

}
